/*
 * @Author: 0x9DEFA478
 * @Date: 2022-01-22 23:05:55
 * @LastEditTime: 2022-08-20 23:48:33
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "./H_NES_Console.h"
#include "../ConstString/H_NES_ConstString.h"




#define H_NES_PPU_Process_vIncX(_in_Console,_temp_v,_temp_t_uint16) \
do{\
  _temp_v=_in_Console->PPU.Register.Internal.v;\
  if((_temp_v&0x001FU)==0x001FU){\
    _temp_v=(_temp_v&0xFFE0U)^0x0400U;\
  }else{\
    _temp_v+=0x0001U;\
  }\
  _in_Console->PPU.Register.Internal.v=_temp_v;\
}while(0)

#define H_NES_PPU_Process_vIncYSetX(_in_Console,_temp_v,_temp_t_uint16) \
do{\
  _temp_v=_in_Console->PPU.Register.Internal.v;\
  if((_temp_v&0x7000U)==0x7000U){\
    _temp_v&=0x0FFF;\
    _temp_t_uint16=(_temp_v>>5)&0x001FU;\
    if(_temp_t_uint16==0x001DU){\
      _temp_v=(_temp_v&0xFC1FU)^0x0800U;\
    }else if(_temp_t_uint16==0x001FU){\
      _temp_v=_temp_v&0xFC1FU;\
    }else{\
      _temp_v+=0x0020U;\
    }\
  }else{\
    _temp_v+=0x1000U;\
  }\
  _temp_t_uint16=_in_Console->PPU.Register.Internal.t;\
  _temp_v=(_temp_v&(~0x041FU))|(_temp_t_uint16&0x041FU);\
  _in_Console->PPU.Register.Internal.v=_temp_v;\
}while(0)




static void Background_PreFetch(unsigned int LineBufferIndex,H_NES_Console* Console);
static void Background_Renders(unsigned int BufferIndex,H_NES_Console* Console);
static Hbyte OAM_PreFetch(unsigned int line,H_NES_Console* Console);
static void Sprite_Renders(unsigned int BufferIndex,H_NES_Console* Console);




void H_NES_PPU_RendrsFrame_NTSC(H_NES_Console* Console){

#define oH_NES_CPU_Execute(_in_PPUCLK,_in_Console) \
  CPU_Execute((_in_PPUCLK)*vH_NES_PPU_NTSC_MCLKDiv,_in_Console)

  void (*CPU_Execute)(Hint32 MCLK,H_NES_Console* Console);

  unsigned int line;

  Huint16 t_uint16;
  Hint32 Cycle;

  Hbyte PPUCTRL;
  Hbyte PPUMASK;
  Huint16 v;
  
  unsigned int BufferIndex;

  Hbyte MemLoc;
  int Shift;
  void (*MMC3_A12_Rise)(unsigned int,void*);
  Hint32 MMC3_CountDelay;


  if(Console->Cartridge.Option.CPUTick==NULL){
    CPU_Execute=H_NES_CPU_Execute_NTSC;
  }else{
    CPU_Execute=H_NES_CPU_Execute_NTSC_CPUTick;
  }
  MMC3_A12_Rise=Console->Cartridge.Option.MMC3_A12_Rise;
  MMC3_CountDelay=Console->CompatibilityOption.MMC3_CountDelay;

  //0,0 0,0
  if(Console->PPU.Renderer.IsOddFrame!=0){
    Console->PPU.Renderer.IsOddFrame=0;
  }else{
    Console->PPU.Renderer.IsOddFrame=-1;
    oH_NES_CPU_Execute(1,Console);
  }

  //0,1 0,240
  for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(BufferIndex+2U,Console);
      }

      //渲染
      Background_Renders(BufferIndex,Console);

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }
  }

  //0,241 0,248
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(32U,Console);
    }

    //渲染
    Background_Renders(30U,Console);

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,249 0,260
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //渲染
    Background_Renders(31U,Console);

    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
  }
  oH_NES_CPU_Execute(4,Console);

  //0,261 0,324
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //OAM预取
    MemLoc=OAM_PreFetch(0U,Console);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

      //大约260~261
      if(MMC3_CountDelay>0){
        oH_NES_CPU_Execute(MMC3_CountDelay,Console);
      }
      Cycle=64-MMC3_CountDelay;
      if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        if(Cycle<8){
          oH_NES_CPU_Execute(Cycle,Console);
          Cycle=0;
        }else{
          oH_NES_CPU_Execute(8,Console);
          Cycle-=8;
        }
      }
      //每两个精灵获取之间的间隙(8个精灵共7个间隙)
      for(Shift=0;Shift<7;Shift++){
        if(((MemLoc>>Shift)&0x03U)==0x02U){
          MMC3_A12_Rise(0U,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
      }
      if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        oH_NES_CPU_Execute(Cycle,Console);
      }

    }else{
      oH_NES_CPU_Execute(64,Console);
    }
  
  }else{
    oH_NES_CPU_Execute(64,Console);
    for(BufferIndex=0;BufferIndex<256;BufferIndex++){
      Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
    }
  }
  //输出一行的 数据
  Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,0);

  //0,325 0,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,329 0,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,337 0,340
  oH_NES_CPU_Execute(4,Console);




  //1,0 239,340
  for(line=1U;line<240U;line++){

    //line,0 line,0
    oH_NES_CPU_Execute(1,Console);

    //line,1 line,240
    for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
      oH_NES_CPU_Execute(8,Console);
      PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
      if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

        //背景预取
        if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
          Background_PreFetch(BufferIndex+2U,Console);
        }

        //渲染
        if(((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U)&&((BufferIndex!=0U)||((PPUMASK&vH_NES_PPU_PPUMASK_M)!=0U))){
          //允许渲染
          Sprite_Renders(BufferIndex,Console);
        }else{
          Background_Renders(BufferIndex,Console);
        }

        H_NES_PPU_Process_vIncX(Console,v,t_uint16);
      }
    }

    //line,241 line,248
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(32U,Console);
      }

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(30U,Console);
      }else{
        Background_Renders(30U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,249 line,260
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(31U,Console);
      }else{
        Background_Renders(31U,Console);
      }

      H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
    }
    oH_NES_CPU_Execute(4,Console);

    //line,261 line,324
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //OAM预取
      MemLoc=OAM_PreFetch(line,Console);

      //MMC3 A12判定
      if(MMC3_A12_Rise!=NULL){
        PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

        //大约260~261
        if(MMC3_CountDelay>0){
          oH_NES_CPU_Execute(MMC3_CountDelay,Console);
        }
        Cycle=64-MMC3_CountDelay;
        if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
        //每两个精灵获取之间的间隙(8个精灵共7个间隙)
        for(Shift=0;Shift<7;Shift++){
          if(((MemLoc>>Shift)&0x03U)==0x02U){
            MMC3_A12_Rise(line,Console);
          }
          if(Cycle>0){
            if(Cycle<8){
              oH_NES_CPU_Execute(Cycle,Console);
              Cycle=0;
            }else{
              oH_NES_CPU_Execute(8,Console);
              Cycle-=8;
            }
          }
        }
        if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          oH_NES_CPU_Execute(Cycle,Console);
        }

      }else{
        oH_NES_CPU_Execute(64,Console);
      }
    
    }else{
      oH_NES_CPU_Execute(64,Console);
      for(BufferIndex=0;BufferIndex<256;BufferIndex++){
        Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
      }
    }
    //输出一行的 数据
    Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,line);

    //line,324 line,328
    oH_NES_CPU_Execute(4,Console);
    for(BufferIndex=0;BufferIndex<33;BufferIndex++){
      Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
    }
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(0U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,329 line,336
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(1U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,337 line,341
    oH_NES_CPU_Execute(4,Console);
  }

  Console->PPU.Register.Internal.IsAddXY=0;

  //240,0 261,0
  oH_NES_CPU_Execute(341+1,Console);
  //Set Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_V;
  Cycle=Console->CompatibilityOption.VblankNMI_Delay;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  //Suspend NMI
  if((Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL]&vH_NES_PPU_PPUCTRL_V)!=0U){
    Console->CPU.Status|=vH_NES_CPU_Status_NMI_Suspend;
  }
  Cycle=341*20 - Cycle;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  
  //261,1 261,260
  //Clear Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]&=(~(vH_NES_PPU_PPUSTATUS_V|vH_NES_PPU_PPUSTATUS_S|vH_NES_PPU_PPUSTATUS_O));
  Console->PPU.Register.Internal.IsAddXY=-1;
  oH_NES_CPU_Execute(260,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_S){
        MMC3_A12_Rise(261U,Console);
      }else if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B))==vH_NES_PPU_PPUCTRL_H){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //261,261 261,304
  oH_NES_CPU_Execute(44,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //vert(v) = vert(t)
    v=Console->PPU.Register.Internal.v;
    t_uint16=Console->PPU.Register.Internal.t;
    Console->PPU.Register.Internal.v=(v&(~0x7BE0U))|(t_uint16&0x7BE0U);
  }

  //261,305 261,324
  oH_NES_CPU_Execute(20,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_B){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //261,325 261,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //261,329 261,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }
  

  //261,337 261,341
  oH_NES_CPU_Execute(4,Console);

#undef oH_NES_CPU_Execute

}

void H_NES_PPU_RendrsFrame_PAL(H_NES_Console* Console){

#define oH_NES_CPU_Execute(_in_PPUCLK,_in_Console) \
  CPU_Execute((_in_PPUCLK)*vH_NES_PPU_PAL_MCLKDiv,_in_Console)

  void (*CPU_Execute)(Hint32 MCLK,H_NES_Console* Console);

  unsigned int line;

  Huint16 t_uint16;
  Hint32 Cycle;

  Hbyte PPUCTRL;
  Hbyte PPUMASK;
  Huint16 v;
  
  unsigned int BufferIndex;

  Hbyte MemLoc;
  int Shift;
  void (*MMC3_A12_Rise)(unsigned int,void*);
  Hint32 MMC3_CountDelay;


  if(Console->Cartridge.Option.CPUTick==NULL){
    CPU_Execute=H_NES_CPU_Execute_PAL;
  }else{
    CPU_Execute=H_NES_CPU_Execute_PAL_CPUTick;
  }
  MMC3_A12_Rise=Console->Cartridge.Option.MMC3_A12_Rise;
  MMC3_CountDelay=Console->CompatibilityOption.MMC3_CountDelay;

  //0,0 0,0
  if(Console->PPU.Renderer.IsOddFrame!=0){
    Console->PPU.Renderer.IsOddFrame=0;
  }else{
    Console->PPU.Renderer.IsOddFrame=-1;
  }
  oH_NES_CPU_Execute(1,Console);

  //0,1 0,240
  for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(BufferIndex+2U,Console);
      }

      //渲染
      Background_Renders(BufferIndex,Console);

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }
  }

  //0,241 0,248
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(32U,Console);
    }

    //渲染
    Background_Renders(30U,Console);

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,249 0,260
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //渲染
    Background_Renders(31U,Console);

    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
  }
  oH_NES_CPU_Execute(4,Console);

  //0,261 0,324
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //OAM预取
    MemLoc=OAM_PreFetch(0U,Console);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

      //大约260~261
      if(MMC3_CountDelay>0){
        oH_NES_CPU_Execute(MMC3_CountDelay,Console);
      }
      Cycle=64-MMC3_CountDelay;
      if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        if(Cycle<8){
          oH_NES_CPU_Execute(Cycle,Console);
          Cycle=0;
        }else{
          oH_NES_CPU_Execute(8,Console);
          Cycle-=8;
        }
      }
      //每两个精灵获取之间的间隙(8个精灵共7个间隙)
      for(Shift=0;Shift<7;Shift++){
        if(((MemLoc>>Shift)&0x03U)==0x02U){
          MMC3_A12_Rise(0U,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
      }
      if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        oH_NES_CPU_Execute(Cycle,Console);
      }

    }else{
      oH_NES_CPU_Execute(64,Console);
    }
  
  }else{
    oH_NES_CPU_Execute(64,Console);
    for(BufferIndex=0;BufferIndex<256;BufferIndex++){
      Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
    }
  }
  //输出一行的 数据
  Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,0);

  //0,325 0,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,329 0,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,337 0,340
  oH_NES_CPU_Execute(4,Console);




  //1,0 239,340
  for(line=1U;line<240U;line++){

    //line,0 line,0
    oH_NES_CPU_Execute(1,Console);

    //line,1 line,240
    for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
      oH_NES_CPU_Execute(8,Console);
      PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
      if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

        //背景预取
        if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
          Background_PreFetch(BufferIndex+2U,Console);
        }

        //渲染
        if(((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U)&&((BufferIndex!=0U)||((PPUMASK&vH_NES_PPU_PPUMASK_M)!=0U))){
          //允许渲染
          Sprite_Renders(BufferIndex,Console);
        }else{
          Background_Renders(BufferIndex,Console);
        }

        H_NES_PPU_Process_vIncX(Console,v,t_uint16);
      }
    }

    //line,241 line,248
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(32U,Console);
      }

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(30U,Console);
      }else{
        Background_Renders(30U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,249 line,260
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(31U,Console);
      }else{
        Background_Renders(31U,Console);
      }

      H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
    }
    oH_NES_CPU_Execute(4,Console);

    //line,261 line,324
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //OAM预取
      MemLoc=OAM_PreFetch(line,Console);

      //MMC3 A12判定
      if(MMC3_A12_Rise!=NULL){
        PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

        //大约260~261
        if(MMC3_CountDelay>0){
          oH_NES_CPU_Execute(MMC3_CountDelay,Console);
        }
        Cycle=64-MMC3_CountDelay;
        if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
        //每两个精灵获取之间的间隙(8个精灵共7个间隙)
        for(Shift=0;Shift<7;Shift++){
          if(((MemLoc>>Shift)&0x03U)==0x02U){
            MMC3_A12_Rise(line,Console);
          }
          if(Cycle>0){
            if(Cycle<8){
              oH_NES_CPU_Execute(Cycle,Console);
              Cycle=0;
            }else{
              oH_NES_CPU_Execute(8,Console);
              Cycle-=8;
            }
          }
        }
        if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          oH_NES_CPU_Execute(Cycle,Console);
        }

      }else{
        oH_NES_CPU_Execute(64,Console);
      }
    
    }else{
      oH_NES_CPU_Execute(64,Console);
      for(BufferIndex=0;BufferIndex<256;BufferIndex++){
        Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
      }
    }
    //输出一行的 数据
    Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,line);

    //line,324 line,328
    oH_NES_CPU_Execute(4,Console);
    for(BufferIndex=0;BufferIndex<33;BufferIndex++){
      Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
    }
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(0U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,329 line,336
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(1U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,337 line,341
    oH_NES_CPU_Execute(4,Console);
  }

  Console->PPU.Register.Internal.IsAddXY=0;

  //240,0 331,0
  oH_NES_CPU_Execute(341+1,Console);
  //Set Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_V;
  Cycle=Console->CompatibilityOption.VblankNMI_Delay;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  //Suspend NMI
  if((Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL]&vH_NES_PPU_PPUCTRL_V)!=0U){
    Console->CPU.Status|=vH_NES_CPU_Status_NMI_Suspend;
  }
  Cycle=341*70 - Cycle;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  
  //311,1 311,260
  //Clear Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]&=(~(vH_NES_PPU_PPUSTATUS_V|vH_NES_PPU_PPUSTATUS_S|vH_NES_PPU_PPUSTATUS_O));
  Console->PPU.Register.Internal.IsAddXY=-1;
  oH_NES_CPU_Execute(260,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_S){
        MMC3_A12_Rise(261U,Console);
      }else if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B))==vH_NES_PPU_PPUCTRL_H){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //311,261 311,304
  oH_NES_CPU_Execute(44,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //vert(v) = vert(t)
    v=Console->PPU.Register.Internal.v;
    t_uint16=Console->PPU.Register.Internal.t;
    Console->PPU.Register.Internal.v=(v&(~0x7BE0U))|(t_uint16&0x7BE0U);
  }

  //311,305 311,324
  oH_NES_CPU_Execute(20,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_B){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //311,325 311,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //311,329 311,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }
  

  //311,337 261,341
  oH_NES_CPU_Execute(4,Console);

#undef oH_NES_CPU_Execute

}

void H_NES_PPU_RendrsFrame_Dendy(H_NES_Console* Console){

#define oH_NES_CPU_Execute(_in_PPUCLK,_in_Console) \
  CPU_Execute((_in_PPUCLK)*vH_NES_PPU_Dendy_MCLKDiv,_in_Console)

  void (*CPU_Execute)(Hint32 MCLK,H_NES_Console* Console);

  unsigned int line;

  Huint16 t_uint16;
  Hint32 Cycle;

  Hbyte PPUCTRL;
  Hbyte PPUMASK;
  Huint16 v;
  
  unsigned int BufferIndex;

  Hbyte MemLoc;
  int Shift;
  void (*MMC3_A12_Rise)(unsigned int,void*);
  Hint32 MMC3_CountDelay;


  if(Console->Cartridge.Option.CPUTick==NULL){
    CPU_Execute=H_NES_CPU_Execute_Dendy;
  }else{
    CPU_Execute=H_NES_CPU_Execute_Dendy_CPUTick;
  }
  MMC3_A12_Rise=Console->Cartridge.Option.MMC3_A12_Rise;
  MMC3_CountDelay=Console->CompatibilityOption.MMC3_CountDelay;

  //0,0 0,0
  if(Console->PPU.Renderer.IsOddFrame!=0){
    Console->PPU.Renderer.IsOddFrame=0;
  }else{
    Console->PPU.Renderer.IsOddFrame=-1;
  }
  oH_NES_CPU_Execute(1,Console);

  //0,1 0,240
  for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(BufferIndex+2U,Console);
      }

      //渲染
      Background_Renders(BufferIndex,Console);

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }
  }

  //0,241 0,248
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(32U,Console);
    }

    //渲染
    Background_Renders(30U,Console);

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,249 0,260
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

    //渲染
    Background_Renders(31U,Console);

    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
  }
  oH_NES_CPU_Execute(4,Console);

  //0,261 0,324
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //OAM预取
    MemLoc=OAM_PreFetch(0U,Console);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

      //大约260~261
      if(MMC3_CountDelay>0){
        oH_NES_CPU_Execute(MMC3_CountDelay,Console);
      }
      Cycle=64-MMC3_CountDelay;
      if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        if(Cycle<8){
          oH_NES_CPU_Execute(Cycle,Console);
          Cycle=0;
        }else{
          oH_NES_CPU_Execute(8,Console);
          Cycle-=8;
        }
      }
      //每两个精灵获取之间的间隙(8个精灵共7个间隙)
      for(Shift=0;Shift<7;Shift++){
        if(((MemLoc>>Shift)&0x03U)==0x02U){
          MMC3_A12_Rise(0U,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
      }
      if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
        MMC3_A12_Rise(0U,Console);
      }
      if(Cycle>0){
        oH_NES_CPU_Execute(Cycle,Console);
      }

    }else{
      oH_NES_CPU_Execute(64,Console);
    }
  
  }else{
    oH_NES_CPU_Execute(64,Console);
    for(BufferIndex=0;BufferIndex<256;BufferIndex++){
      Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
    }
  }
  //输出一行的 数据
  Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,0);

  //0,325 0,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,329 0,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //0,337 0,340
  oH_NES_CPU_Execute(4,Console);




  //1,0 239,340
  for(line=1U;line<240U;line++){

    //line,0 line,0
    oH_NES_CPU_Execute(1,Console);

    //line,1 line,240
    for(BufferIndex=0U;BufferIndex<30U;BufferIndex++){
    
      oH_NES_CPU_Execute(8,Console);
      PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
      if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

        //背景预取
        if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
          Background_PreFetch(BufferIndex+2U,Console);
        }

        //渲染
        if(((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U)&&((BufferIndex!=0U)||((PPUMASK&vH_NES_PPU_PPUMASK_M)!=0U))){
          //允许渲染
          Sprite_Renders(BufferIndex,Console);
        }else{
          Background_Renders(BufferIndex,Console);
        }

        H_NES_PPU_Process_vIncX(Console,v,t_uint16);
      }
    }

    //line,241 line,248
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(32U,Console);
      }

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(30U,Console);
      }else{
        Background_Renders(30U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,249 line,260
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){

      //渲染
      if((PPUMASK&vH_NES_PPU_PPUMASK_s)!=0U){
        //允许渲染
        Sprite_Renders(31U,Console);
      }else{
        Background_Renders(31U,Console);
      }

      H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);
    }
    oH_NES_CPU_Execute(4,Console);

    //line,261 line,324
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //OAM预取
      MemLoc=OAM_PreFetch(line,Console);

      //MMC3 A12判定
      if(MMC3_A12_Rise!=NULL){
        PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];

        //大约260~261
        if(MMC3_CountDelay>0){
          oH_NES_CPU_Execute(MMC3_CountDelay,Console);
        }
        Cycle=64-MMC3_CountDelay;
        if(((PPUCTRL&vH_NES_PPU_PPUCTRL_B)==0U)&&((MemLoc&0x01U)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          if(Cycle<8){
            oH_NES_CPU_Execute(Cycle,Console);
            Cycle=0;
          }else{
            oH_NES_CPU_Execute(8,Console);
            Cycle-=8;
          }
        }
        //每两个精灵获取之间的间隙(8个精灵共7个间隙)
        for(Shift=0;Shift<7;Shift++){
          if(((MemLoc>>Shift)&0x03U)==0x02U){
            MMC3_A12_Rise(line,Console);
          }
          if(Cycle>0){
            if(Cycle<8){
              oH_NES_CPU_Execute(Cycle,Console);
              Cycle=0;
            }else{
              oH_NES_CPU_Execute(8,Console);
              Cycle-=8;
            }
          }
        }
        if(((MemLoc&0x80U)==0U)&&((PPUCTRL&vH_NES_PPU_PPUCTRL_B)!=0U)){
          MMC3_A12_Rise(line,Console);
        }
        if(Cycle>0){
          oH_NES_CPU_Execute(Cycle,Console);
        }

      }else{
        oH_NES_CPU_Execute(64,Console);
      }
    
    }else{
      oH_NES_CPU_Execute(64,Console);
      for(BufferIndex=0;BufferIndex<256;BufferIndex++){
        Console->PPU.LineBuffer_Output[BufferIndex]=0x3FU;
      }
    }
    //输出一行的 数据
    Console->LL_Function.Console.RendersLine(Console->LL_Function.v,Console->PPU.LineBuffer_Output,line);

    //line,324 line,328
    oH_NES_CPU_Execute(4,Console);
    for(BufferIndex=0;BufferIndex<33;BufferIndex++){
      Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
    }
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(0U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,329 line,336
    oH_NES_CPU_Execute(8,Console);
    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
      
      //背景预取
      if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
        Background_PreFetch(1U,Console);
      }

      H_NES_PPU_Process_vIncX(Console,v,t_uint16);
    }

    //line,337 line,341
    oH_NES_CPU_Execute(4,Console);
  }

  Console->PPU.Register.Internal.IsAddXY=0;

  //240,0 311,0
  oH_NES_CPU_Execute(341*51+1,Console);
  //Set Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_V;
  Cycle=Console->CompatibilityOption.VblankNMI_Delay;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  //Suspend NMI
  if((Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL]&vH_NES_PPU_PPUCTRL_V)!=0U){
    Console->CPU.Status|=vH_NES_CPU_Status_NMI_Suspend;
  }
  Cycle=341*20 - Cycle;
  if(Cycle>0){
    oH_NES_CPU_Execute(Cycle,Console);
  }
  
  //311,1 311,260
  //Clear Vblank
  Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]&=(~(vH_NES_PPU_PPUSTATUS_V|vH_NES_PPU_PPUSTATUS_S|vH_NES_PPU_PPUSTATUS_O));
  Console->PPU.Register.Internal.IsAddXY=-1;
  oH_NES_CPU_Execute(260,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    H_NES_PPU_Process_vIncYSetX(Console,v,t_uint16);

    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_S){
        MMC3_A12_Rise(261U,Console);
      }else if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B))==vH_NES_PPU_PPUCTRL_H){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //311,261 311,304
  oH_NES_CPU_Execute(44,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //vert(v) = vert(t)
    v=Console->PPU.Register.Internal.v;
    t_uint16=Console->PPU.Register.Internal.t;
    Console->PPU.Register.Internal.v=(v&(~0x7BE0U))|(t_uint16&0x7BE0U);
  }

  //311,305 311,324
  oH_NES_CPU_Execute(20,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    //MMC3 A12判定
    if(MMC3_A12_Rise!=NULL){
      PPUCTRL=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
      if((PPUCTRL&(vH_NES_PPU_PPUCTRL_H|vH_NES_PPU_PPUCTRL_B|vH_NES_PPU_PPUCTRL_S))==vH_NES_PPU_PPUCTRL_B){
        MMC3_A12_Rise(261U,Console);
      }
    }
  }

  //311,325 311,328
  oH_NES_CPU_Execute(4,Console);
  for(BufferIndex=0;BufferIndex<33;BufferIndex++){
    Console->PPU.Renderer.LineBuffer[BufferIndex]=0U;
  }
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(0U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }

  //311,329 311,336
  oH_NES_CPU_Execute(8,Console);
  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((PPUMASK&(vH_NES_PPU_PPUMASK_b|vH_NES_PPU_PPUMASK_s))!=0U){
    
    //背景预取
    if((PPUMASK&vH_NES_PPU_PPUMASK_b)!=0U){
      Background_PreFetch(1U,Console);
    }

    H_NES_PPU_Process_vIncX(Console,v,t_uint16);
  }
  

  //311,337 261,341
  oH_NES_CPU_Execute(4,Console);

#undef oH_NES_CPU_Execute

}




static void Background_PreFetch(unsigned int LineBufferIndex,H_NES_Console* Console){

  Huint16 t_uint16;
  Huint32* tp_uint32;

  Huint16 v;
  Huint16 Pattern;
  Huint32 Attribute;
  Huint32 LowPattern;
  Huint32 HighPattern;


  if((Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL]&vH_NES_PPU_PPUCTRL_B)!=0U){
    Pattern=0x1000U;
  }else{
    Pattern=0x0000U;
  }

  v=Console->PPU.Register.Internal.v;
  Attribute=Console->PPU.NameTable[(v&0x0C00U)>>10][0x03C0U+(((v>>4)&0x0038U)|((v>>2)&0x0007U))];
  t_uint16=(v&0x0002U)|((v>>4)&0x0004U);
  Attribute=((Attribute>>t_uint16)<<2)&0x0000000CU;
  t_uint16=((Huint16)Console->PPU.NameTable[(v&0x0C00U)>>10][v&0x03FFU])<<4;
  t_uint16+=Pattern+((v>>12)&0x0007U);
  LowPattern=Console->Cartridge.CHR_Read(t_uint16,Console);
  HighPattern=Console->Cartridge.CHR_Read(t_uint16+8U,Console);
  

  tp_uint32=Console->PPU.Table->PatternToLineBuffer;

  LowPattern=tp_uint32[LowPattern];
  HighPattern=tp_uint32[HighPattern];

  Console->PPU.Renderer.LineBuffer[LineBufferIndex]=LowPattern|(HighPattern<<1)|((LowPattern|HighPattern)*Attribute);

}

static void Background_Renders(unsigned int BufferIndex,H_NES_Console* Console){

  Hbyte t_byte;
  Huint32* tp_uint32;

  Hbyte PPUMASK;

  Huint32 Buffer;

  Huint32 Pattern_Mask;

  Hbyte* Palettes;
  Hbyte* Output;


  PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
  if((BufferIndex==0U)&&((PPUMASK&vH_NES_PPU_PPUMASK_m)==0U)){
    Buffer=0U;
  }else{
    t_byte=Console->PPU.Register.Internal.x;
    if(t_byte!=0x00U){
      tp_uint32=Console->PPU.Renderer.LineBuffer;
      t_byte*=4U;
      Buffer=(tp_uint32[BufferIndex]>>t_byte);
      Buffer|=(tp_uint32[BufferIndex+1]<<(32U-t_byte));
    }else{
      Buffer=Console->PPU.Renderer.LineBuffer[BufferIndex];
    }
  }

  Palettes=&Console->PPU.Palettes[0];
  Pattern_Mask=0x0000000FU;
  Output=&Console->PPU.LineBuffer_Output[BufferIndex<<3];
  if((PPUMASK&vH_NES_PPU_PPUMASK_Gray)==0U){
    Output[0]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[1]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[2]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[3]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[4]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[5]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[6]=Palettes[Buffer&Pattern_Mask];
    Buffer>>=4;
    Output[7]=Palettes[Buffer&Pattern_Mask];
  }else{
    t_byte=0x30U;
    Output[0]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[1]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[2]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[3]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[4]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[5]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[6]=Palettes[Buffer&Pattern_Mask]&t_byte;
    Buffer>>=4;
    Output[7]=Palettes[Buffer&Pattern_Mask]&t_byte;
  }

}

static Hbyte OAM_PreFetch(unsigned int line,H_NES_Console* Console){

  int i;
  int Count;
  Hbyte MemLoc;

  Huint16 t_uint16;

  Huint16 Pattern;
  unsigned int y;
  Huint32 LowPattern;
  Huint32 HighPattern;
  Huint32 Attributes;
  Hbyte Priority;
  unsigned int x;
  int xMod8Mul4;
  int xMod8;
  int xDiv8;
  unsigned int Offset;
  
  H_NES_PPU_SubOAMInfo* SubOAMInfo;
  Hbyte OAM_Count;

  Huint32* PatternToLineBuffer;
  Hbyte* ReverseBitTable;

  Count=0;
  MemLoc=0x00U;


  PatternToLineBuffer=Console->PPU.Table->PatternToLineBuffer;
  ReverseBitTable=Console->PPU.Table->ReverseBitTable;

  //清空SubOAM
  for(i=0;i<32;i++){
    SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[i];
    SubOAMInfo->Priority=0x00U;
    SubOAMInfo->ExistSprite0=0U;
    SubOAMInfo->OAM_Count=0U;
  }

  Pattern=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUCTRL];
  if((Pattern&vH_NES_PPU_PPUCTRL_H)!=0U){
    //8x16
    

    //精灵0
    y=Console->PPU.OAM[0];
    if(line>=y){
      Offset=line-y;
      if(Offset<16U){
        //精灵0可显示


        t_uint16=(Huint16)Console->PPU.OAM[1];
        Attributes=Console->PPU.OAM[2];
        if((Attributes&0x80U)!=0U){
          //垂直翻转
          Offset=15U-Offset;
        }
        if(Offset<8U){
          if((t_uint16&0x0001U)==0U){
            t_uint16=(t_uint16<<4)+Offset;
          }else{
            MemLoc|=0x01U;
            t_uint16=0x1000U+((t_uint16&(~0x0001U))<<4)+Offset;
          }
        }else{
          Offset-=8U;
          if((t_uint16&0x0001U)==0U){
            t_uint16=0x0010U+(t_uint16<<4)+Offset;
          }else{
            MemLoc|=0x01U;
            t_uint16=0x1010U+((t_uint16&(~0x0001U))<<4)+Offset;
          }
        }

        if((Attributes&0x40U)!=0U){
          //水平翻转
          LowPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16,Console)];
          HighPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16+8U,Console)];
        }else{
          LowPattern=Console->Cartridge.CHR_Read(t_uint16,Console);
          HighPattern=Console->Cartridge.CHR_Read(t_uint16+8U,Console);
        }

        LowPattern=PatternToLineBuffer[LowPattern];
        HighPattern=PatternToLineBuffer[HighPattern];
        Priority=(Attributes>>5)&0x01U;
        Attributes=(LowPattern|HighPattern)*((Attributes&0x03U)<<2);
        Attributes|=LowPattern|(HighPattern<<1);


        x=Console->PPU.OAM[3];
        xMod8=(int)(x&0x00000007U);
        xDiv8=(int)(x>>3);
        xMod8Mul4=xMod8*4;

        SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[xDiv8];
        SubOAMInfo->Buffer[0]=Attributes<<xMod8Mul4;
        SubOAMInfo->BufferValid[0]=0xFFFFFFFFU<<xMod8Mul4;
        SubOAMInfo->Priority=Priority;
        SubOAMInfo->OAM_Count=1U;
        SubOAMInfo->ExistSprite0=0xFFU;
        if((xMod8!=0)&&(xDiv8<31)){
          xMod8Mul4=32-xMod8Mul4;
          SubOAMInfo=&SubOAMInfo[1];
          SubOAMInfo->Buffer[0]=Attributes>>xMod8Mul4;
          SubOAMInfo->BufferValid[0]=0xFFFFFFFFU>>xMod8Mul4;
          SubOAMInfo->Priority=Priority;
          SubOAMInfo->OAM_Count=1U;
          SubOAMInfo->ExistSprite0=0xFFU;
        }

        Count++;
      }
    }


    //剩余的精灵
    for(i=4;i<256;i+=4){
      
      y=Console->PPU.OAM[i];
      if(line>=y){
        Offset=line-y;
        if(Offset<16U){
          //找到要显示的精灵

          if(Count>7){
            Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_O;//精灵溢出
            return MemLoc;
          }


          t_uint16=(Huint16)Console->PPU.OAM[i+1];
          Attributes=Console->PPU.OAM[i+2];
          if((Attributes&0x80U)!=0U){
            //垂直翻转
            Offset=15U-Offset;
          }
          if(Offset<8U){
            if((t_uint16&0x0001U)==0U){
              t_uint16=(t_uint16<<4)+(Huint16)Offset;
            }else{
              MemLoc|=0x01U<<Count;
              t_uint16=0x1000U+((t_uint16&(~0x0001U))<<4)+(Huint16)Offset;
            }
          }else{
            Offset-=8U;
            if((t_uint16&0x0001U)==0U){
              t_uint16=0x0010U+(t_uint16<<4)+(Huint16)Offset;
            }else{
              MemLoc|=0x01U<<Count;
              t_uint16=0x1010U+((t_uint16&(~0x0001U))<<4)+(Huint16)Offset;
            }
          }

          if((Attributes&0x40U)!=0U){
            //水平翻转
            LowPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16,Console)];
            HighPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16+8U,Console)];
          }else{
            LowPattern=Console->Cartridge.CHR_Read(t_uint16,Console);
            HighPattern=Console->Cartridge.CHR_Read(t_uint16+8U,Console);
          }

          LowPattern=PatternToLineBuffer[LowPattern];
          HighPattern=PatternToLineBuffer[HighPattern];
          Priority=(Attributes>>5)&0x01U;
          Attributes=(LowPattern|HighPattern)*((Attributes&0x03U)<<2);
          Attributes|=LowPattern|(HighPattern<<1);


          x=Console->PPU.OAM[i+3];
          xMod8=(int)(x&0x00000007U);
          xDiv8=(int)(x>>3);
          xMod8Mul4=xMod8*4;

          SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[xDiv8];
          OAM_Count=SubOAMInfo->OAM_Count;
          SubOAMInfo->Buffer[OAM_Count]=Attributes<<xMod8Mul4;
          SubOAMInfo->BufferValid[OAM_Count]=0xFFFFFFFFU<<xMod8Mul4;
          SubOAMInfo->Priority|=Priority<<OAM_Count;
          SubOAMInfo->OAM_Count=OAM_Count+1U;
          if((xMod8!=0)&&(xDiv8<31)){
            xMod8Mul4=32-xMod8Mul4;
            SubOAMInfo=&SubOAMInfo[1];
            OAM_Count=SubOAMInfo->OAM_Count;
            SubOAMInfo->Buffer[OAM_Count]=Attributes>>xMod8Mul4;
            SubOAMInfo->BufferValid[OAM_Count]=0xFFFFFFFFU>>xMod8Mul4;
            SubOAMInfo->Priority|=Priority<<OAM_Count;
            SubOAMInfo->OAM_Count=OAM_Count+1U;
          }

          Count++;
        }
      }

    }
    
    if(Count<8U){
      MemLoc|=((0x01U<<(8-Count))-0x01U)<<Count;
    }
  }else{
    if((Pattern&vH_NES_PPU_PPUCTRL_S)!=0U){
      Pattern=0x1000U;
      MemLoc=0xFFU;
    }else{
      Pattern=0x0000U;
    }
    //8*8
    

    //精灵0
    y=Console->PPU.OAM[0];
    if(line>=y){
      Offset=line-y;
      if(Offset<8U){
        //精灵0可显示


        t_uint16=((Huint16)Console->PPU.OAM[1])<<4;
        Attributes=Console->PPU.OAM[2];
        if((Attributes&0x80U)!=0U){
          //垂直翻转
          t_uint16+=Pattern+(0x0007U-(Huint16)Offset);
        }else{
          t_uint16+=Pattern+(Huint16)Offset;
        }
        if((Attributes&0x40U)!=0U){
          //水平翻转
          LowPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16,Console)];
          HighPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16+8U,Console)];
        }else{
          LowPattern=Console->Cartridge.CHR_Read(t_uint16,Console);
          HighPattern=Console->Cartridge.CHR_Read(t_uint16+8U,Console);
        }

        LowPattern=PatternToLineBuffer[LowPattern];
        HighPattern=PatternToLineBuffer[HighPattern];
        Priority=(Attributes>>5)&0x01U;
        Attributes=(LowPattern|HighPattern)*((Attributes&0x03U)<<2);
        Attributes|=LowPattern|(HighPattern<<1);


        x=Console->PPU.OAM[3];
        xMod8=(int)(x&0x00000007U);
        xDiv8=(int)(x>>3);
        xMod8Mul4=xMod8*4;

        SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[xDiv8];
        SubOAMInfo->Buffer[0]=Attributes<<xMod8Mul4;
        SubOAMInfo->BufferValid[0]=0xFFFFFFFFU<<xMod8Mul4;
        SubOAMInfo->Priority=Priority;
        SubOAMInfo->OAM_Count=1U;
        SubOAMInfo->ExistSprite0=0xFFU;
        if((xMod8!=0)&&(xDiv8<31)){
          xMod8Mul4=32-xMod8Mul4;
          SubOAMInfo=&SubOAMInfo[1];
          SubOAMInfo->Buffer[0]=Attributes>>xMod8Mul4;
          SubOAMInfo->BufferValid[0]=0xFFFFFFFFU>>xMod8Mul4;
          SubOAMInfo->Priority=Priority;
          SubOAMInfo->OAM_Count=1U;
          SubOAMInfo->ExistSprite0=0xFFU;
        }

        Count++;
      }
    }


    //剩余的精灵
    for(i=4;i<256;i+=4){
      
      y=Console->PPU.OAM[i];
      if(line>=y){
        Offset=line-y;
        if(Offset<8U){
          //找到要显示的精灵

          if(Count>7){
            Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_O;//精灵溢出
            return MemLoc;
          }


          t_uint16=((Huint16)Console->PPU.OAM[i+1])<<4;
          Attributes=Console->PPU.OAM[i+2];
          if((Attributes&0x80U)!=0U){
            //垂直翻转
            t_uint16+=Pattern+(0x0007U-(Huint16)Offset);
          }else{
            t_uint16+=Pattern+(Huint16)Offset;
          }
          if((Attributes&0x40U)!=0U){
            //水平翻转
            LowPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16,Console)];
            HighPattern=ReverseBitTable[Console->Cartridge.CHR_Read(t_uint16+8U,Console)];
          }else{
            LowPattern=Console->Cartridge.CHR_Read(t_uint16,Console);
            HighPattern=Console->Cartridge.CHR_Read(t_uint16+8U,Console);
          }

          LowPattern=PatternToLineBuffer[LowPattern];
          HighPattern=PatternToLineBuffer[HighPattern];
          Priority=(Attributes>>5)&0x01U;
          Attributes=(LowPattern|HighPattern)*((Attributes&0x03U)<<2);
          Attributes|=LowPattern|(HighPattern<<1);


          x=Console->PPU.OAM[i+3];
          xMod8=(int)(x&0x00000007U);
          xDiv8=(int)(x>>3);
          xMod8Mul4=xMod8*4;

          SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[xDiv8];
          OAM_Count=SubOAMInfo->OAM_Count;
          SubOAMInfo->Buffer[OAM_Count]=Attributes<<xMod8Mul4;
          SubOAMInfo->BufferValid[OAM_Count]=0xFFFFFFFFU<<xMod8Mul4;
          SubOAMInfo->Priority|=Priority<<OAM_Count;
          SubOAMInfo->OAM_Count=OAM_Count+1U;
          if((xMod8!=0)&&(xDiv8<31)){
            xMod8Mul4=32-xMod8Mul4;
            SubOAMInfo=&SubOAMInfo[1];
            OAM_Count=SubOAMInfo->OAM_Count;
            SubOAMInfo->Buffer[OAM_Count]=Attributes>>xMod8Mul4;
            SubOAMInfo->BufferValid[OAM_Count]=0xFFFFFFFFU>>xMod8Mul4;
            SubOAMInfo->Priority|=Priority<<OAM_Count;
            SubOAMInfo->OAM_Count=OAM_Count+1U;
          }

          Count++;
        }
      }

    }
    
  }

  return MemLoc;
}

static void Sprite_Renders(unsigned int BufferIndex,H_NES_Console* Console){
  
  int i;

  Hbyte t_byte;
  Huint32* tp_uint32;

  Hbyte PPUMASK;

  
  Huint32 Buffer;
  Huint32 Buffer_Mask;
  Huint32 OutputBufferUndefined_Mask;
  Huint32 OutputSpriteBuffer;
  Huint32 OutputSpriteBuffer_Mask;
  Huint32 SpriteBuffer;
  Huint32 SpriteBuffer_Mask;
  Huint32 SpriteBuffer_Valid;
  

  H_NES_PPU_SubOAMInfo* SubOAMInfo;
  unsigned int SubOAM_OAMIndex;
  unsigned int SubOAM_Count;
  Huint32 Priority;

  Hbyte* Palettes;
  Hbyte* Sprite_Palettes;
  Hbyte* Output;


  SubOAMInfo=&Console->PPU.Renderer.SubOAMInfo[BufferIndex];
  SubOAM_Count=SubOAMInfo->OAM_Count;
  if(!(SubOAM_Count>0U)){
    Background_Renders(BufferIndex,Console);
  }else{

    PPUMASK=Console->PPU.Register.Register[vH_NES_PPU_Register_PPUMASK];
    if((BufferIndex==0U)&&((PPUMASK&vH_NES_PPU_PPUMASK_m)==0U)){
      Buffer=0U;
    }else{
      t_byte=Console->PPU.Register.Internal.x;
      if(t_byte!=0x00U){
        tp_uint32=Console->PPU.Renderer.LineBuffer;
        t_byte*=4U;
        Buffer=(tp_uint32[BufferIndex]>>t_byte);
        Buffer|=(tp_uint32[BufferIndex+1]<<(32U-t_byte));
      }else{
        Buffer=Console->PPU.Renderer.LineBuffer[BufferIndex];
      }
    }

    Buffer_Mask=((Buffer|(Buffer>>1))&0x11111111U)*0x0000000FU;
    Buffer&=Buffer_Mask;


    SubOAM_OAMIndex=0U;
    Priority=SubOAMInfo->Priority;
    OutputBufferUndefined_Mask=0xFFFFFFFFU;
    OutputSpriteBuffer=0x0U;
    OutputSpriteBuffer_Mask=0U;
    
    if(SubOAMInfo->ExistSprite0!=0U){
      //存在Sprite0


      //精灵0渲染
      SpriteBuffer=SubOAMInfo->Buffer[SubOAM_OAMIndex];
      SpriteBuffer_Valid=SubOAMInfo->BufferValid[SubOAM_OAMIndex];
      if((Buffer_Mask&((SpriteBuffer|(SpriteBuffer>>1))&0x11111111U))!=0U){
        //Sprite 0 Hit
        Console->PPU.Register.Register[vH_NES_PPU_Register_PPUSTATUS]|=vH_NES_PPU_PPUSTATUS_S;
      }
      if((Priority&0x01U)==0U){
        //在背景前
        SpriteBuffer&=OutputBufferUndefined_Mask;
        
        SpriteBuffer_Mask=((SpriteBuffer|(SpriteBuffer>>1))&0x11111111U)*0x0000000FU;
        OutputBufferUndefined_Mask&=(~SpriteBuffer_Mask);
      }else{
        //在背景后
        SpriteBuffer&=OutputBufferUndefined_Mask&(~Buffer_Mask);

        SpriteBuffer_Mask=((SpriteBuffer|(SpriteBuffer>>1))&0x11111111U)*0x0000000FU;
        OutputBufferUndefined_Mask&=(~(SpriteBuffer_Mask|(Buffer_Mask&SpriteBuffer_Valid)));
      }
      OutputSpriteBuffer|=SpriteBuffer;
      OutputSpriteBuffer_Mask|=SpriteBuffer_Mask;

      Priority>>=1;
      SubOAM_OAMIndex++;
    }


    //剩余精灵渲染循环
    while(SubOAM_OAMIndex<SubOAM_Count){
    
      SpriteBuffer=SubOAMInfo->Buffer[SubOAM_OAMIndex];
      SpriteBuffer_Valid=SubOAMInfo->BufferValid[SubOAM_OAMIndex];
      if((Priority&0x01U)==0U){
        //在背景前
        SpriteBuffer&=OutputBufferUndefined_Mask;
        
        SpriteBuffer_Mask=((SpriteBuffer|(SpriteBuffer>>1))&0x11111111U)*0x0000000FU;
        OutputBufferUndefined_Mask&=(~SpriteBuffer_Mask);
      }else{
        //在背景后
        SpriteBuffer&=OutputBufferUndefined_Mask&(~Buffer_Mask);

        SpriteBuffer_Mask=((SpriteBuffer|(SpriteBuffer>>1))&0x11111111U)*0x0000000FU;
        OutputBufferUndefined_Mask&=(~(SpriteBuffer_Mask|(Buffer_Mask&SpriteBuffer_Valid)));
      }
      OutputSpriteBuffer|=SpriteBuffer;
      OutputSpriteBuffer_Mask|=SpriteBuffer_Mask;

      Priority>>=1;
      SubOAM_OAMIndex++;
    }

    
    

    Buffer=(Buffer&(~OutputSpriteBuffer_Mask))|OutputSpriteBuffer;

    //混合背景和精灵
    Palettes=&Console->PPU.Palettes[0];
    Sprite_Palettes=&Palettes[16];
    Output=&Console->PPU.LineBuffer_Output[BufferIndex<<3];
    Buffer_Mask=0x0000000FU;
    if((PPUMASK&vH_NES_PPU_PPUMASK_Gray)==0U){
      for(i=0;i<8;i++){
        if((OutputSpriteBuffer_Mask&Buffer_Mask)==0U){
          Output[i]=Palettes[Buffer&Buffer_Mask];
        }else{
          Output[i]=Sprite_Palettes[Buffer&Buffer_Mask];
        }
        Buffer>>=4;
        OutputSpriteBuffer_Mask>>=4;
      }
    }else{
      t_byte=0x30U;
      for(i=0;i<8;i++){
        if((OutputSpriteBuffer_Mask&Buffer_Mask)==0U){
          Output[i]=Palettes[Buffer&Buffer_Mask]&t_byte;
        }else{
          Output[i]=Sprite_Palettes[Buffer&Buffer_Mask]&t_byte;
        }
        Buffer>>=4;
        OutputSpriteBuffer_Mask>>=4;
      }
    }


  }
  
}



